package cn.topcode.unicorn.utils;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.thoughtworks.xstream.mapper.MapperWrapper;

public class XmlUtil {

    private static XStream getXStream() {
        return new XStream(new DomDriver("utf-8", new NoNameCoder()) {



            @Override
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new PrettyPrintWriter(out) {
                    // 对所有xml节点的转换都增加CDATA标记
                    boolean cdata = true;

                    @Override
                    @SuppressWarnings("rawtypes")
                    public void startNode(String name, Class clazz) {
                        super.startNode(name, clazz);
                    }

                    @Override
                    public String encodeNode(String name) {
                        return name;
                    }


                    @Override
                    protected void writeText(QuickWriter writer, String text) {
                        if (cdata) {
                            writer.write("<![CDATA[");
                            writer.write(text);
                            writer.write("]]>");
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        }) {
            @Override
            protected MapperWrapper wrapMapper(MapperWrapper next) {
                return new MapperWrapper(next) {
                    @Override
                    public boolean shouldSerializeMember(Class definedIn, String fieldName) {
                        if (definedIn == Object.class) {
                            return false;
                        }
                        return super.shouldSerializeMember(definedIn, fieldName);
                    }
                };
            }
        };
    }
    
    private XmlUtil() {}

    /**
     * 从xml字符串中解析出对象
     * @author Unicorn Lien
     * 2016年12月4日 上午11:29:35 创建
     * @param xml
     * @param clazz
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T parse(String xml, Class<T> clazz) {
        XStream xs = getXStream();
        xs.processAnnotations(clazz);
        return (T) xs.fromXML(xml);
    }
    
    /**
     * 从xml输入流中解析出对象
     * @author Unicorn Lien
     * 2016年12月4日 上午11:30:50 创建
     * @param in
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T> T parse(InputStream in, Class<T> clazz) {
        XStream xs = getXStream();
        xs.processAnnotations(clazz);
        return (T) xs.fromXML(in);
    }
    
    /**
     * 对象转换成xml字符串
     * @author Unicorn Lien
     * 2016年12月4日 上午11:33:41 创建
     * @param obj
     * @return
     */
    public static String toXml(Object obj) {
        XStream xs = getXStream();
        xs.processAnnotations(obj.getClass());
        return xs.toXML(obj);
    }
    
    /**
     * 对象转换成xml流并输出
     * @author Unicorn Lien
     * 2016年12月4日 上午11:35:47 创建
     * @param obj
     * @param out
     */
    public static void toXml(Object obj, OutputStream out) {
        XStream xs = getXStream();
        xs.processAnnotations(obj.getClass());
        xs.toXML(obj, out);
    }
}
